<template>
  <div class="components-imports">
    <slot :open="open"></slot>
    <input ref="input" type="file" accept=".xlsx,.xls,.csv" style="display: none" @change="onChange" />
    <t-dialog
      v-model:visible="show"
      :width="700"
      :header="lang.t('title')"
      destroyOnClose
      :closeOnOverlayClick="false"
      placement="center"
    >
      <template #body>
        <div class="content">
          <t-row :gutter="20">
            <t-col :span="4">
              <div class="bg-box">
                <div class="item wrap">
                  <div class="name">{{ lang.t('total') }}</div>
                  <span>{{ table.total }}</span>
                </div>
              </div>
            </t-col>
            <t-col :span="4">
              <div class="bg-box">
                <div class="item wrap">
                  <div class="name">{{ lang.t('count') }}</div>
                  <span class="color">{{ table.count }}</span>
                </div>
              </div>
            </t-col>
            <t-col :span="4">
              <div class="bg-box">
                <div class="item wrap">
                  <div class="name">{{ lang.t('error') }}</div>
                  <span class="error">{{ table.error }}</span>
                </div>
              </div>
            </t-col>
          </t-row>
          <t-table
            row-key="index"
            table-layout="auto"
            :data="table.header"
            :columns="table.columns"
            :loading="table.loading"
            maxHeight="40vh"
            bordered
            size="small"
            v-if="!start"
          >
            <template #name="{ row }">
              <b>{{ row.name }}</b>
            </template>
            <template #value="{ row }">
              <t-select v-model="row.value" clearable borderless>
                <t-option v-for="(item, index) in option" :key="index" :label="item" :value="index" />
              </t-select>
            </template>
            <template #empty>
              <t-button theme="primary" @click="openFile" variant="outline">{{ lang.t('upload') }}</t-button>
            </template>
          </t-table>
          <t-table
            row-key="index"
            table-layout="auto"
            :data="log.data"
            :columns="log.columns"
            maxHeight="40vh"
            bordered
            size="small"
            v-else
          />
        </div>
      </template>
      <template #footer>
        <t-button theme="primary" v-if="!start" @click="onSubmit">
          {{ lang.t('button') }}
        </t-button>
        <template v-else>
          <t-progress theme="plump" v-if="!over" :percentage="progress" status="active" />
          <t-button theme="success" v-else @click="onReboot">
            {{ lang.t('reboot') }}
          </t-button>
        </template>
      </template>
    </t-dialog>
  </div>
</template>
<script setup>
  import { ref, reactive } from 'vue'
  import app from '@/app'
  import { read, utils } from 'xlsx';

  const lang = app.lang.space('components.imports')
  const props = defineProps(['option', 'handle'])
  const input = ref()
  const show = ref(false)
  const start = ref(false)
  const over = ref(false)
  const progress = ref(0)
  const table = reactive({
    header: [],
    data: [],
    loading: false,
    count: 0,
    error: 0,
    total: 0,
    columns: [{
      title: lang.t('table.index'),
      colKey: 'index',
      width: 50,
      align: 'center'
    }, {
      title: lang.t('table.name'),
      colKey: 'name',
      cell: 'name',
      width: 300
    }, {
      title: lang.t('table.value'),
      colKey: 'value',
      cell: 'value',
      fixed: 'right',
      align: 'right'
    }]
  })
  const log = reactive({
    data: [],
    columns: [{
      title: lang.t('log.index'),
      colKey: 'index',
      width: 100,
      align: 'center'
    }, {
      title: lang.t('log.message'),
      colKey: 'message',
      cell: 'message',
    }]
  })

  const open = () => {
    show.value = true
  }

  const openFile = () => {
    input.value.value = null
    input.value.click()
  }

  const onChange = async (e) => {
    table.loading = true

    // 获取数据
    const file = await e.target.files[0].arrayBuffer()
    const wb = read(file)

    // 获取表格
    const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {header: 1})
    const header = []
    // 循环表头
    data.shift().forEach((name, index) => {
      header.push({
        index: index + 1,
        name,
        value: null
      })
    })
    table.data = data
    table.header = header
    table.total = data.length
    table.loading = false
  }

  const onSubmit = async () => {
    start.value = true
    
    // 循环表格
    for (let i = 0; i < table.data.length; i++) {
      const data = {}

      // 循环表头
      table.header.forEach((item, index) => {
        if(item.value) {
          data[item.value] = table.data[i][index]
        }
      })

      // 处理数据
      try{
        await props.handle(data)
        onProgress()
      } catch(e) {
        console.error(e)
        // 异常处理
        onProgress({
          index: i + 1,
          message: e.message
        })
      }
    }

    over.value = true
  }

  // 更新进条度
  const onProgress = (error = false) => {
    // 是否错误
    if(error) {
      // 记录日志
      log.data.push(error)
      table.error += 1
    } else {
      table.count += 1
    }
    
    // 计算进度
    progress.value = parseInt((table.count + table.error) / table.total * 100)
  }

  // 重新开始
  const onReboot = () => {
    over.value = false
    start.value = false
    progress.value = 0
    log.data = []
    table.header = []
    table.data = []
    table.total = 0
    table.count = 0
    table.error = 0
  }
</script>
<style lang="scss">
  @import '@/style/global';

  .components-imports{
    @include table-size(12px);

    display: inline;

    .bg-box{
      padding: 20px !important;
    }

    .content{
      overflow: hidden;
    }

    .t-dialog{
      background-color: $color-bg;
    }

    .item{  
      color: $color-title;
      font-size: 16px;
      line-height: 20px;
      
      .name{
        color: $color-body;
        padding-bottom: 10px;
        font-size: 14px;
      }

      span{
        font-weight: bold;
      }

      .color{
        color: $color;
      }
      .error{
        color: $color-error;
      }
    }
  }
</style>